using System.ComponentModel;
using System.Xml;
using System.Xml.Serialization;
using uTILLIty.Rave.Contract.Schema;
using uTILLIty.Rave.Contract.StorageAdapter;

namespace uTILLIty.Rave.Contract.Configuration
{
	/// <summary>
	/// The root configuration object, defining all information required for the <see cref="IStorageAdapter"/>
	/// to be able to create directories
	/// </summary>
	[XmlRoot(Namespace = WellKnownSchemas.RaveConfiguration, IsNullable = false)]
	public class Configuration
	{
		/// <summary>
		/// the Default constructor used by the XML serializer
		/// </summary>
		public Configuration()
		{
			CreateRootDirectory = true;
		}

		/// <summary>
		/// Creates a minimal configuration object
		/// </summary>
		/// <param name="targetSystem">The identifier of a registered <see cref="IStorageAdapter"/></param>
		/// <param name="rootDirectory">The starting-point from which the configuration is applied.
		/// Interpreted by the <see cref="IStorageAdapter"/></param>
		public Configuration(string targetSystem, string rootDirectory)
		{
			TargetSystem = targetSystem;
			RootDirectory = rootDirectory;
		}

		/// <summary>
		/// The identifier of a registered <see cref="IStorageAdapter"/>
		/// </summary>
		/// <remarks>
		/// The ConfigurationManager (see Core library) locates the corresponding <see cref="IStorageAdapter"/>
		/// by this value. So make sure that the adapters are registered accordingly
		/// </remarks>
		[XmlAttribute("targetSystem")]
		public string TargetSystem { get; set; }

		/// <summary>
		/// The starting-point from which the configuration is applied.
		/// Interpreted by the <see cref="IStorageAdapter"/>
		/// </summary>
		/// <remarks>
		/// The adapter's <see cref="IStorageAdapter.ValidateRootPath"/> implementation should
		/// create an error, if it doesn't exist and <see cref="CreateRootDirectory"/> is false,
		/// or creation is not supported
		/// </remarks>
		[XmlAttribute("rootDirectory")]
		public string RootDirectory { get; set; }

		/// <summary>
		/// Wether to throw an error, if the <see cref="RootDirectory"/> does not exist, or auto-create it,
		/// if the provider supports it. 
		/// </summary>
		/// <remarks>
		/// The adapter's <see cref="IStorageAdapter.ValidateRootPath"/> implementation should
		/// create an error, if creation is not supported
		/// </remarks>
		[XmlAttribute("createRootDirectory"), DefaultValue(true)]
		public bool CreateRootDirectory { get; set; }

		/// <summary>
		/// A list of directories to process and/or create
		/// </summary>
		/// <seealso cref="IStorageAdapter.ValidateDirectory"/>
		[XmlArray(IsNullable = true)]
		public Directory[] Directories { get; set; }

		/// <summary>
		/// A list of member-details, which are referenced by the <see cref="Directories"/>
		/// </summary>
		/// <remarks>
		/// The ConfigurationValidator (see Core library) ensures that all referenced members are
		/// also defined in this array
		/// </remarks>
		/// <seealso cref="IStorageAdapter.ValidateMember"/>
		[XmlArray(IsNullable = false)]
		[XmlArrayItem(typeof(Member))]
#pragma warning disable 612,618
		[XmlArrayItem(typeof(User))]
		[XmlArrayItem(typeof(Group))]
#pragma warning restore 612,618
		public Member[] Members { get; set; }

		/// <summary>
		/// Additional information provided to the <see cref="IStorageAdapter"/> so it can
		/// initialize itself
		/// </summary>
		/// <remarks>
		/// The adapter's <see cref="IStorageAdapter.ValidateAdapterConfiguration"/> implementation
		/// should ensure that all information stated can be interpreted
		/// </remarks>
		[XmlAnyElement("StorageAdapterConfiguration")]
		public XmlNode StorageAdapterConfiguration { get; set; }
	}
}